# gozerbot/db.py
#
#

""" mysql interface """

__copyright__ = 'this file is in the public domain'

from gozerbot.config import config
from gozerbot.generic import rlog
import gozerbot.thr as thr
import thread, time, os

class Db(object):

    """ this class implements an database connection. it connects to the 
        database on initialisation.
    """

    def __init__(self, ping=None):
        self.stop = 0
        self.db = None
        self.lock = thread.allocate_lock()
        self.connect()
        # see if we have to start a database ping thread
        if ping:
            thr.start_new_thread(self.pingloop, ())

    def __del__(self):
        """ set stop and close database """
        self.stop = 1 
        rlog(5, 'db', "closing database")
        try:
            self.db.close()
        except:
            pass

    def connect(self):
        """ connect to the database """
        try:
            self.db = MySQLdb.connect(db=config['dbname'], \
host=config['dbhost'], user=config['dbuser'], passwd=config['dbpasswd'])
        except Exception, ex:
            reason = str(ex)
            rlog(10, 'db', 'error connecting to database: %s' % reason)
            os._exit(1)
        # connect is ok
        rlog(5, 'db', "database ok")
        return 1

    def execute(self, execstr, args=None):
        """ execute string on database """
        self.lock.acquire()
        result = None
        try:
            # get cursor
            cursor = self.cursor()
            # check if there is a string in args and if its a REGEXP string
            # use re.escape in that case otherwise use MySQLdb'd escape_string
            if args:
                rlog(-2, 'db', 'exec %s %s' % (execstr, args))
                nritems = cursor.execute(execstr, args)
            else:
                rlog(-2, 'db', 'exec %s' % execstr)
                nritems = cursor.execute(execstr)
            # fetch results
            result = cursor.fetchall()
            # if no result set insertid and if that fails set nritems 
            if not result:
                try:
                    result = self.db.insert_id()
                except:
                    pass
                if not result:
                    result = nritems
            # see if we need to commit the query
            if 'INSERT' in execstr or 'DELETE' in execstr or 'UPDATE' \
in execstr:
                self.commit()
        except Exception, ex:
            self.lock.release()
            raise
        self.lock.release()
        return result

    def cursor(self):
        """ return cursor to the database """
        return self.db.cursor()

    def commit(self):
        """ do a commit on the datase """
        self.db.commit()

    def pingloop(self):
        """ database ping loop """
        rlog(0, 'db', 'starting database ping loop')
        while not self.stop:
            time.sleep(60)
            if self.stop:
                break
            try:
                self.ping()
            except Exception, ex:
                rlog(10, 'db', str(ex))
        rlog(10, 'db', 'stopping database ping loop')

    def ping(self):
        """ do a ping """
        return self.db.ping()

    def close(self):
        """ close database """
        self.db.close()

if config['dbenable']:
    import MySQLdb
    db = Db(ping=1)
else:
    db = None
